package com.example.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.PropertyNamingStrategy;
import com.alibaba.fastjson.serializer.SerializeConfig;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.entity.ContentType;
import org.apache.http.nio.entity.NStringEntity;
import org.apache.http.util.EntityUtils;
import org.elasticsearch.action.admin.indices.flush.FlushRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.client.*;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.client.indices.GetIndexResponse;
import org.elasticsearch.common.xcontent.XContentType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.DigestUtils;

import java.io.IOException;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;


@Slf4j
public class EsUtil {

    @Autowired
    static RestClient restClient;

    public static List<Map<String,Object>> getBuckets(String resultString,int id){

        List<Map<String ,Object>> maps = new ArrayList<>();
        Object parse = JSON.parse(resultString);
        Map<String,Object> aggregations = (Map<String, Object>) ((Map) parse).get("aggregations");
        Map<String,Object> statistics = (Map<String, Object>) aggregations.get("statistics");
        List<Map<String,Object>> buckets = (List<Map<String,Object>>)statistics.get("buckets");
        Map<String,Object> map = null;
        if (id<=2) {
            for (Map<String, Object> bucket : buckets) {
                map = new HashMap<>();
                map.put("ip", bucket.get("key"));
                map.put("number", bucket.get("doc_count"));
                maps.add(map);
            }
        }
        else if(id>2&&id<5){
            for (Map<String, Object> bucket : buckets) {
                map = new HashMap<>();
                map.put("ip", bucket.get("key"));
                map.put("cameraNum", ((Map<String,Object>)bucket.get("cameranum")).get("value"));
                maps.add(map);
            }
        }
        else {
            for (Map<String, Object> bucket : buckets) {
                map = new HashMap<>();
                map.put("type", bucket.get("key"));
                map.put("number", bucket.get("doc_count"));
                maps.add(map);
            }
        }
        return maps;
    }

    public static List<Map<String,Object>> getBuckets(String resultString) {
        List<Map<String, Object>> maps = new ArrayList<>();
        Object parse = JSON.parse(resultString);
        Map<String, Object> aggregations = (Map<String, Object>) ((Map) parse).get("aggregations");
        for (String key : aggregations.keySet()) {
            Map<String, Object> statistics = (Map<String, Object>) aggregations.get(key);
                getMaps(statistics,maps,key,new HashMap<>());
            }
            return maps;
        }

    /**
     *
     * @param statistics 统计数据
     * @param maps 对数据分析后的map列表
     * @param key  当前聚合的名称
     * @param map  单行统计数据
     * @return
     */
    public static List<Map<String, Object>>  getMaps(Map<String,Object> statistics,List<Map<String, Object>> maps,String key,Map<String,Object> map) {
        if (statistics.get("value") != null) {
            map.put(key, statistics.get("value"));
            if(!maps.contains(map))
                maps.add(map);
        }
        if (statistics.get("buckets") != null) {
            List<Map<String, Object>> buckets = (List<Map<String, Object>>) statistics.get("buckets");
            for (Map<String, Object> bucket : buckets) {
                //map = new HashMap<>();
                //新建一个map，并包含传入map的值
                map = new HashMap<>(map);
                map.put(key, bucket.get("key"));
                map.put(key+"_number", bucket.get("doc_count"));
                if (bucket.keySet().size() == 2) {
                    maps.add(map);
                } else {
                    for (String secondKey : bucket.keySet()) {
                        if  (secondKey != "key" && secondKey != "doc_count")
                            getMaps(((Map<String, Object>) bucket.get(secondKey)), maps, secondKey, map);
                    }
                }

            }
        }
        return maps;
    }
    public static Response executeDsl(String dsl, String index, RestClient restClient){
        HttpEntity entity = new NStringEntity(dsl, ContentType.APPLICATION_JSON);
        Response response = null;

        String endpoint = new StringBuilder().append("/").append(index).append("/").append("_search")
                .toString();
        Request request = new Request("GET",endpoint);
        request.setEntity(entity);
        try {
            response = restClient.performRequest(request);
        } catch (
                IOException e) {
            e.printStackTrace();
        }
        return response;
    }



    public static List<String> listIndexs(RestHighLevelClient client,String s) {

        try {
            // 构建请求,注意*号的写法
//            GetIndexRequest getIndexRequest = new GetIndexRequest("ip_addr*");
            GetIndexRequest getIndexRequest = new GetIndexRequest(s);

            // 构建获取所有索引的请求：org.elasticsearch.client.indices.GetIndexRequest

            GetIndexResponse getIndexResponse = client.indices().get(getIndexRequest, RequestOptions.DEFAULT);

            // 获取所有的索引
            String[] indices = getIndexResponse.getIndices();

            // 转化为list形式
            List<String> asList = Arrays.asList(indices);

            // 复制一下，不然不能追加
            return new ArrayList<>(asList);
        } catch (Exception e) {
            log.error("获取所有索引失败：{}", e);
        }
        return null;
    }

//    public static Set<String> getIndexes(RestHighLevelClient restClient){
//        try {
//            GetAliasesRequest request = new GetAliasesRequest("ip_addr");
//            GetAliasesResponse getAliasesResponse =  restClient.indices().getAlias(request,RequestOptions.DEFAULT);
//            Map<String, Set<AliasMetaData>> map = getAliasesResponse.getAliases();
//            Set<String> indices = map.keySet();
//            return indices;
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//        return null;
//    }

    public static Response executeDsl(String dsl, List<String> indexes, RestClient restClient){
        HttpEntity entity = new NStringEntity(dsl, ContentType.APPLICATION_JSON);
        Response response = null;
        StringBuilder stringBuilder = new StringBuilder().append("/");

        if (indexes.size()==0){
            return null;
        }
        for (String s : indexes) {
            stringBuilder.append(s).append(",");
        }
        //去掉添加的最后一个逗号
        stringBuilder.deleteCharAt(stringBuilder.length()-1);
        String endpoint = stringBuilder.append("/").append("_search").toString();
        Request request = new Request("GET",endpoint);
        request.setEntity(entity);
        try {
            response = restClient.performRequest(request);
        } catch (
                IOException e) {
            e.printStackTrace();
        }
        return response;
    }



    public static Long getTotalCount(String dsl, String index, RestClient restClient){
        Long count = 0L;
        HttpEntity entity = new NStringEntity(dsl, ContentType.APPLICATION_JSON);
        Response response = null;

        String endpoint = new StringBuilder().append("/").append(index).append("/").append("_search")
                .toString();
        Request request = new Request("GET",endpoint);
        request.setEntity(entity);
        try {
            response = restClient.performRequest(request);
        } catch (
                IOException e) {
            e.printStackTrace();
        }
////     response
//        String resultString = null;
//        try {
//            resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//        Object parse = JSON.parse(resultString);
//        count = EsUtil.parseLong(((Map<String,Object>)parse).get("count"));
        Map<String, Object> statistic = EsUtil.getStatistic(response);
        for (String key : statistic.keySet()) {
          count =  EsUtil.parseLong(statistic.get(key));
        }
        return count;
    }

    public static Long getTotalCount(String dsl, List<String> indexes, RestClient restClient){
        Long count = 0L;
        HttpEntity entity = new NStringEntity(dsl, ContentType.APPLICATION_JSON);
        Response response = null;

        StringBuilder stringBuilder = new StringBuilder().append("/");
        for (String s : indexes) {
            stringBuilder.append(s).append(",");
        }
        //去掉添加的最后一个逗号
        stringBuilder.deleteCharAt(stringBuilder.length()-1);
        String endpoint = stringBuilder.append("/").append("_search").toString();
        Request request = new Request("GET",endpoint);
        request.setEntity(entity);
        try {
            response = restClient.performRequest(request);
        } catch (
                IOException e) {
            e.printStackTrace();
        }
////     response
//        String resultString = null;
//        try {
//            resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//        Object parse = JSON.parse(resultString);
//        count = EsUtil.parseLong(((Map<String,Object>)parse).get("count"));
        Map<String, Object> statistic = EsUtil.getStatistic(response);
        for (String key : statistic.keySet()) {
            count =  EsUtil.parseLong(statistic.get(key));
        }
        return count;
    }



    public static Map<String,Object> getStatistic(Response response){

        if(null == response) {

            return null;
        }

        Map<String,Object> statistic = new HashMap<>();
        if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
            // 提取数据
            String resultString = null;
            try {
                resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
            } catch (IOException e) {
                e.printStackTrace();
            }
            Object parse = JSON.parse(resultString);
            Map<String, Object> aggregations = (Map<String, Object>) ((Map) parse).get("aggregations");
            for (String key : aggregations.keySet()) {
                Map<String,Object> aggregation = (Map<String, Object>) aggregations.get(key);

                if (aggregation.get("value")!=null){
                    statistic.put(key,aggregation.get("value"));
                }
                else {
                    List<Map<String, Object>> buckets = (List<Map<String, Object>>) aggregation.get("buckets");
                    if (buckets != null) {
                        for (Map<String, Object> bucket : buckets) {
                            for (String s : bucket.keySet()) {
                                if (!s.equals("doc_count")&&!s.equals("key")){
                                    Map<String,Object> temp = (Map<String,Object>)bucket.get(s);
                                    statistic.put(s,temp.get("value"));
                                }
                            }
                        }
                    }
                }
            }
            return statistic;
        }
        return statistic;
    }

    public static Map<String,Object> getBucketsMap(Response response){

        if(null == response) {

            return null;
        }

        Map<String,Object> statistic = new HashMap<>();
        if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
            // 提取数据
            String resultString = null;
            try {
                resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
            } catch (IOException e) {
                e.printStackTrace();
            }
            Object parse = JSON.parse(resultString);
            Map<String, Object> aggregations = (Map<String, Object>) ((Map) parse).get("aggregations");
            if (aggregations != null) {
                for (String key : aggregations.keySet()) {
                    Map<String, Object> aggregation = (Map<String, Object>) aggregations.get(key);
                    List<Map<String, Object>> buckets = (List<Map<String, Object>>) aggregation.get("buckets");
                    if (buckets != null) {
                        for (Map<String, Object> bucket : buckets) {
                            statistic.put(bucket.get("key").toString(), bucket.get("doc_count"));
                        }
                    }
                }
            }
            return statistic;
        }
        return statistic;
    }



    public static List<Map<String,Object>> getStatisticList(Response response) {

        if(null == response) {

            return null;
        }

        List<Map<String, Object>> maps = new ArrayList<>();
        if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
            // 提取数据
            String resultString = null;
            try {
                resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
            } catch (IOException e) {
                e.printStackTrace();
            }
            Object parse = JSON.parse(resultString);
            Map<String, Object> aggregations = (Map<String, Object>) ((Map) parse).get("aggregations");
            Set<String> keySet = aggregations.keySet();
            Map<String, Object> name = (Map<String, Object>) aggregations.get(keySet.iterator().next());
            List<Map<String, Object>> buckets = (List<Map<String, Object>>) name.get("buckets");
            if (buckets != null) {
                for (Map<String, Object> bucket : buckets) {
                    Map<String, Object> map = new HashMap<>();
                    for (String s : bucket.keySet()) {
                        if (!s.equals("doc_count")&&!s.equals("key")&&!s.equals("key_as_string")){
                            Map<String,Object> temp = (Map<String,Object>)bucket.get(s);
                            if (temp.get("value")!=null) {
                                map.put(s, temp.get("value"));
                            }else {
                                map.put(s,temp);
                            }
                        }else {
                            map.put(s,bucket.get(s));
                        }
                    }
                    maps.add(map);
                }
            }
        }
        return maps;
    }

    public static List<Map<String,Object>> getStatisticList_time(Response response,Long insert_time) {

        if (null == response) {

            return null;
        }

        List<Map<String, Object>> maps = new ArrayList<>();
        if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
            // 提取数据
            String resultString = null;
            try {
                resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
            } catch (IOException e) {
                e.printStackTrace();
            }
            Object parse = JSON.parse(resultString);
            Map<String, Object> aggregations = (Map<String, Object>) ((Map) parse).get("aggregations");
            Set<String> keySet = aggregations.keySet();
            Map<String, Object> name = (Map<String, Object>) aggregations.get(keySet.iterator().next());
            List<Map<String, Object>> buckets = (List<Map<String, Object>>) name.get("buckets");
            if (buckets != null) {
                for (Map<String, Object> bucket : buckets) {
                    Map<String, Object> map = new HashMap<>();
                    for (String s : bucket.keySet()) {
                        if (!s.equals("doc_count")&&!s.equals("key")&&!s.equals("key_as_string")){
                            Map<String,Object> temp = (Map<String,Object>)bucket.get(s);
                            if (temp.get("value")!=null) {
                                map.put(s, temp.get("value"));
                            }else {
                                map.put(s,temp);
                            }
                        }else {
                            map.put(s,bucket.get(s));
                        }
                    }
                    map.put("insert_time",insert_time);
                    maps.add(map);
                }
            }
        }
        return maps;
    }

    /**
     * 获取明细
     * @param response
     * @return
     */
    public static List<Map<String,Object>> getDataDetail(Response response) {

        if(null == response) {

            return null;
        }

        List<Map<String, Object>> maps = new ArrayList<>();

        if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {

            // 提取数据
            String resultString = null;
            try {

                resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
            } catch (IOException e) {

                e.printStackTrace();
            }

            JSONObject jsonObject = JSON.parseObject(resultString);
            JSONObject jsonObject2 = jsonObject.getJSONObject("hits");
            JSONArray hits = jsonObject2.getJSONArray("hits");

            hits.forEach(re -> {
                Map<String,Object> map =  JSON.parseObject(re.toString()).getJSONObject("_source");
                maps.add(map);
            });

        }

        return maps;
    }



    /**
     * 根据输入的时间判断需要取ES中哪些时间范围的索引
     * 如：ly_flow
     * @param map
     * @param index
     * @param restHighLevelClient
     * @return
     */
    public static List<String> getIndexes(Map<String,Object> map,String index,RestHighLevelClient restHighLevelClient){
        List<String> indexes = new ArrayList<>();
        SimpleDateFormat indexSuffixFormat = new SimpleDateFormat("yyyyMMdd");
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(Calendar.DATE, 0);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        Long startTimeStamp = 0l;
        Long endTimeStamp = 0l;

        if (map.get("startTime") instanceof Date){
            startTimeStamp = ((Date)map.get("startTime")).getTime();
        }else {
            startTimeStamp = Long.parseLong(map.get("startTime").toString());
        }
        if (map.get("endTime") instanceof Date){
            endTimeStamp = ((Date)map.get("endTime")).getTime();
        }else {
            endTimeStamp = Long.parseLong(map.get("endTime").toString());
        }
        //如果流量数据是当天发生的或是在当天之后，就从当天的索引取数据
        if (startTimeStamp >= calendar.getTimeInMillis()) {
            indexes.add(index + indexSuffixFormat.format(new Date()));
            return indexes;
        }
        //否则则是非当天数据，取以前各日的表的索引来取数据
        else {
            List<String> dates = null;
            List<String> indexlist = EsUtil.listIndexs(restHighLevelClient, index+"*");
            if (indexlist==null)
            {
                indexlist = new ArrayList<>();
            }
            try {
                dates = DateUtils.findDates(startTimeStamp, endTimeStamp,"yyyyMMdd");
            } catch (ParseException e) {
                e.printStackTrace();
            }
            for (String date : dates) {
                for (String tmp : indexlist) {
                    if (tmp.equals(index + date)) {
                        indexes.add(index + date);
                    }
                }
            }
            return indexes;
        }
    }


    /**
     * 将传入的对象解析为Long类型，对象为空则返回NULL
     * @param o
     * @return
     */
    public static Long parseLong(Object o){
        if (o!=null){
            if (o.toString().contains("E")){
                BigDecimal bigDecimal = new BigDecimal(o.toString());
                return bigDecimal.longValue();
            }
            if(o.toString().equals("0.0")){
                return (long)0;
            }
            if (o.toString().contains(".0")){

                return Long.parseLong(o.toString().replace(".0",""));
            }
            return Long.parseLong(o.toString());
        }
        return null;
    }

    /**
     * 将传入的对象解析为Interger类型，对象为空则返回NULL
     * @param o
     * @return
     */
    public static Integer parseInteger(Object o){
        if (o!=null){
            if(o.toString().equals("0.0")){
                return 0;
            }
            if (o.toString().contains(".0")){

                return Integer.parseInt(o.toString().replace(".0",""));
            }
            return Integer.parseInt(o.toString());
        }
        return null;
    }

    public static Double parseDouble(Object o){
        if (o!=null){
            return Double.parseDouble(o.toString());
        }
        return null;
    }


    public static boolean saveBatch(List<Map<String,Object>> list,String index,RestHighLevelClient restHighLevelClient){
        if (list.size()==0){
            return false;
        }
        BulkRequest bulkRequest = new BulkRequest();
        bulkRequest.timeout("1000s");
//      isExistIndex(index);

        //设置对象转换为JSON时进行驼峰转换
        SerializeConfig config = new SerializeConfig();
        config.setPropertyNamingStrategy(PropertyNamingStrategy.SnakeCase);
        for (Map<String,Object> mp : list) {
            String id= mp.get("key").toString();
            String json = JSON.toJSONString(mp,config);
            bulkRequest.add(new IndexRequest().index(index).id(EsUtil.md5Id(id)).source(json, XContentType.JSON));
        }
        try {
            restHighLevelClient.bulk(bulkRequest,RequestOptions.DEFAULT);
            return true;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }


    public static void deleteByQuery(String dsl,String index,RestClient restClient)
    {
        StringBuilder stringBuilder = new StringBuilder().append("/").append(index);
        HttpEntity entity = new NStringEntity(dsl, ContentType.APPLICATION_JSON);
        String endpoint = stringBuilder.append("/").append("_delete_by_query").toString();
        Request request = new Request("POST",endpoint);
        request.setEntity(entity);
        try {
            restClient.performRequest(request);
        } catch (
                IOException e) {
            e.printStackTrace();
        }
    }


    /**
     * ip反转进行MD5加密
     * @param ip
     * @return
     */
    public static String md5Id(String ip)
    {
        String ip_ =new StringBuilder(ip).reverse().toString();
        return DigestUtils.md5DigestAsHex(ip_.getBytes());
    }


    public static void flushIndex(String indexName,RestHighLevelClient restHighLevelClient)
    {

        try{
            restHighLevelClient.indices().flush(new FlushRequest(indexName),RequestOptions.DEFAULT);

        }catch (Exception e)
        {
            e.printStackTrace();
        }

    }

    public void add(int a)
    {
        a=a-100;
    }

    public static void main(String[] args){
//        int i = 0;
//        for (int a = 0;a<3;a++){
//            i = i+10;
//            for (int b = 0;b<3;b++){
//                if (i==10){
//                    break;
//                }
//                i++;
//            }
//        }
//        System.out.println(i);
        deleteByQuery("{\"query\":{\"match_all\":{}}}","ip_addr_hour24",restClient);
    }
}
